import { useState, memo, useCallback } from 'react';
import './App.css';

function App() {
  console.log('render app');

  const [count, setCount] = useState(1);

  const p1 = 'hello'
  const p2 = 'world'
  // const p3 = () => {
  //   console.log(p1, p2)
  // }

  const p3 = useCallback(() => {
    //如果依赖数组中的值没有发生变化，useCallback 会返回同一个函数引用，从而避免因函数引用变化导致的不必要的重新渲染或重新计算。
    /**
     * 当父组件频繁重新渲染，而子组件依赖于父组件传递的回调函数时，使用 useCallback 可以避免子组件因函数引用变化而重新渲染。
      依赖数组中的值决定了 useCallback 何时返回新的函数引用。如果依赖数组为空，useCallback 只会在组件首次渲染时创建一次函数引用。
     */
    console.log(p1, p2)
  }, [p2, p1])

  const handleChangeCount = () => {
    setCount(count => count + 1);
  };
  return (
    <>
      <div className='card'>
        <span style={{ marginRight: 20 }}>count is {count}</span>
        <br />
        <button onClick={handleChangeCount}>直接修改Count</button>
        <br />
        <br />
        <br />
        {/* <Child p1={p1} p2={p2} /> */}
        <Child p1={p1} p2={p2} p3={p3} />
      </div>
    </>
  );
}

const Child = memo(({ p1, p2, p3 }: { p1: string; p2: string, p3: () => void }) => {
  // p3函数未加useCallback时： p3 这个函数在父组件重新渲染的时候，也会重新被声明了，在进行浅比较的时候，会发现这个p3函数每一次都会改变，导致子组件重新渲染
  p3()
  console.log('子组件 child');
  return (
    <>
      <div>子组件</div>
      <div>{p1}{p2}</div>
    </>
  );
});

// const Child = memo(({ p1, p2 }: { p1: string; p2: string}) => {
//   /**
//    * memo 是 React 提供的一个高阶组件，用于优化性能。
//     当父组件重新渲染时，如果子组件的 props 没有变化，memo 会避免子组件的重新渲染，从而提高应用性能。
//     在你的代码中，Child 组件被 memo 包裹，因此只有当 p1 或 p2 发生变化时，Child 组件才会重新渲染。
//     memo 只是比较 props 的浅层变化，对于深层嵌套的对象或数组，可能需要自定义比较函数。
//    */
//   console.log('子组件 child');
//   return (
//     <>
//       <div>子组件</div>
//       <div>{p1}{p2}</div>
//     </>
//   );
// });

// const Child = ({ p1, p2 }: { p1: string; p2: string} ) => {
//   // 每次更新count时，子组件都会重新渲染
//   console.log('子组件 child');
//   return (
//     <>
//       <div>子组件</div>
//       <div>{p1}{p2}</div>
//     </>
//   );
// };

export default App;
